<?php

namespace App\Services;

use WeChatPay\Builder;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Util\PemUtil;

class WeChatPayService
{
    protected $client;

    public function __construct()
    {
        $config = config('wechatpay');
        $this->client = Builder::factory([
            'mchid' => (string) $config['mch_id'],
            'serial' => env('WECHAT_PAYMENT_SERIAL_NO'),
            'privateKey' => function() use ($config) {
                try {
                    return Rsa::from($config['key_path'], Rsa::KEY_TYPE_PRIVATE);
                } catch (\Exception $e) {
                    \Log::error("WeChatPay privateKey load failed: " . $e->getMessage());
                    throw new \RuntimeException("支付配置错误，请联系管理员");
                }
            },
            'certs' => [
                env('WECHAT_PAYMENT_SERIAL_NO') => Rsa::from($config['cert_path'], Rsa::KEY_TYPE_PUBLIC),
            ],
            'secret' => $config['api_key'],
            'merchant' => [
                'cert' => $config['cert_path'],
                'key'  => $config['key_path'],
            ],
        ]);
    }

    /**
     * 发起 JSAPI 支付
     *
     * @param string $openid 用户 OpenID
     * @param string $orderNo 商户订单号
     * @param int $amount 支付金额（单位：分）
     * @param string $description 商品描述
     * @return array
     */
    public function jsapiPay($openid, $orderNo, $amount, $description)
    {
        $response = $this->client->chain('v3/pay/transactions/jsapi')->post([
            'json' => [
                'mchid' => config('wechatpay.mch_id'),
                'out_trade_no' => $orderNo,
                'appid' => env('WECHAT_APP_ID'),
                'description' => $description,
                'notify_url' => config('wechatpay.notify_url'),
                'amount' => [
                    'total' => $amount,
                    'currency' => 'CNY',
                ],
                'payer' => [
                    'openid' => $openid,
                ],
            ],
        ]);

        return json_decode($response->getBody(), true);
    }
}